﻿using System;
using System.Reflection;
using YawetagLib.Data;
using YawetagLib.Utilities;

namespace YawetagLib.Services
{
    public sealed class ServiceBroker : IServiceFactory
    {
        public ServiceBroker(IServiceFactory serviceFactory)
        {
            ServiceFactory = serviceFactory;
        }

        public ServiceBroker()
            : this(GetServiceFactory())
        {
        }

        private static IServiceFactory GetServiceFactory()
        {
            return DataContextBuilder.IsFactoryRegistered
                ? new DefaultServiceFactory(DataContextBuilder.GetFactory())
                : (IServiceFactory)new PlainServiceFactory();
        }

        public void RegisterService<TService>() where TService : class, IService
        {
            TypeResolver.Register(typeof(TService));
        }

        public void RegisterServices(Assembly assembly)
        {
            TypeResolver.Register(typeof(IService), assembly);
        }

        public void UnRegisterService<TService>() where TService : class, IService
        {
            TypeResolver.UnRegister(typeof(TService));
        }

        public void UnRegisterServices(Assembly assembly)
        {
            TypeResolver.UnRegister(typeof(IService), assembly);
        }

        public IService Get(Type serviceType)
        {
            return ServiceFactory.Get(TypeResolver.Get(serviceType));
        }

        public TService Get<TService>() where TService : IService
        {
            return (TService)Get(typeof(TService));
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing) 
        {
            if (!IsDisposed)
            {
                if (disposing)
                {
                    ServiceFactory.Dispose();
                }
                IsDisposed = true;
            }
        }

        ~ServiceBroker() 
        {
            Dispose(false);
        }

        private IServiceFactory ServiceFactory { get; set; }

        private bool IsDisposed { get; set; }
    }
}
